﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Krile.Common;
using Krile.Kernel;
using Krile.Kernel.Data;

namespace Highkick.API
{
    public class HHAPI
    {
        private readonly Authenticate auth;
        readonly ParseXML XMLParser;
        //hatena hike api
        public HHAPI(Authenticate auth)
        {
            this.auth = auth;
            XMLParser = new ParseXML();
        }

        private Data.HStatus[] GetTimeline(Uri uri)
        {
            var nc = new NetConnect();
            var ret = nc.WebConnect<Data.HStatus[]>(uri, true, "GET", auth.GetCredential(), XMLParser.GetStatuses);
            if (!ret.Succeeded)
            {
                if (ret.Exception != null)
                    throw ret.Exception;
                else
                    throw new Exception(ret.Message);
            }
            return ret.Data;
        }

        private string[] GetKeywords(Uri uri)
        {
            var nc = new NetConnect();
            var ret = nc.WebConnect<string[]>(uri, true, "GET", auth.GetCredential(), XMLParser.GetKeywords);
            if (!ret.Succeeded)
            {
                if (ret.Exception != null)
                    throw ret.Exception;
                else
                    throw new Exception(ret.Message);
            }
            return ret.Data;
        }


        //http://h.hatena.ne.jp/api/statuses/public_timeline.xml
        private DateTime PTSince = DateTime.MinValue;
        public Data.HStatus[] PublicTimeline()
        {
            return GetTimeline(new Uri("http://h.hatena.ne.jp/api/statuses/public_timeline.xml"));
        }
    

        //http://h.hatena.ne.jp/api/statuses/friends_timeline.xml
        private DateTime FTSince = DateTime.MinValue;
        public Data.HStatus[] FriendTimeline()
        {
            return GetTimeline(new Uri("http://h.hatena.ne.jp/api/statuses/friends_timeline.xml"));
        }

        //http://h.hatena.ne.jp/api/statuses/user_timeline.xml
        public Data.HStatus[] UserTimeline()
        {
            return GetTimeline(new Uri("http://h.hatena.ne.jp/api/statuses/user_timeline.xml"));
        }

        //http://h.hatena.ne.jp/api/statuses/keyword_timeline/[keyword].xml
        public Data.HStatus[] KeywordTimeline(string keyword)
        {
            return GetTimeline(new Uri("http://h.hatena.ne.jp/api/statuses/keyword_timeline/" + Uri.EscapeDataString(keyword) + ".xml"));
        }

        //http://h.hatena.ne.jp/api/statuses/show/id.xml
        public Data.HStatus Show(string id)
        {
            var d = GetTimeline(new Uri("http://h.hatena.ne.jp/api/statuses/show/" + id + ".xml"));
            if (d.Length >= 1)
                return d[0];
            else
                return null;
        }

        //http://h.hatena.ne.jp/api/favorites/create/[id].xml
        public bool AddStar(string id)
        {
            var nc = new NetConnect();
            var ret = nc.WebConnectDownloadString(
                new Uri("http://h.hatena.ne.jp/api/favorites/create/" + id + ".xml"),
                "POST", auth.GetCredential());
            return ret.Succeeded;
        }

        //http://h.hatena.ne.jp/api/keywords/hot.xml
        public string[] HotKeywords()
        {
            return GetKeywords(new Uri("http://h.hatena.ne.jp/api/keywords/hot.xml"));
        }

        public string[] GetKeywords(int page)
        {
            return GetKeywords(new Uri("http://h.hatena.ne.jp/api/keywords/list.xml?page=" + page.ToString()));
        }

        //http://h.hatena.ne.jp/api/statuses/update.xml
        public void Update(string status)
        {
            Update(status, null);
        }

        public void Update(string status, string keyword)
        {
            Update(status, null, null);
        }

        public void Update(string status, string keyword, string inReplyTo)
        {
            Update(status, null, null, null);
        }

        public void Update(string status, string keyword, string inReplyTo, string filepath)
        {
            if(String.IsNullOrEmpty(status) && String.IsNullOrEmpty(filepath))
                throw new ArgumentException("statusかfilepathのどちらかがセットされている必要があります。");
            var nc = new NetConnect();
            try{
            if (filepath != null)
            {
                //create multipart/form-data
                var list = new List<NetConnect.SendData>();
                if (!String.IsNullOrEmpty(status))
                    list.Add(new NetConnect.SendData("status", Uri.EscapeDataString(status)));
                if (!String.IsNullOrEmpty(keyword))
                    list.Add(new NetConnect.SendData("keyword", Uri.EscapeDataString(keyword)));
                if (!String.IsNullOrEmpty(inReplyTo))
                    list.Add(new NetConnect.SendData("in_reply_to_status_id", inReplyTo));
                if (!String.IsNullOrEmpty(filepath) && System.IO.File.Exists(filepath))
                    list.Add(new NetConnect.SendData("file", filepath, true));
                nc.WebUpload<string>(
                    nc.CreateRequest(new Uri("http://h.hatena.ne.jp/api/statuses/update.xml"), false),
                    auth.GetCredential(), NetConnect.DefaultStreamReaders.ReadStringByStream,
                    list.ToArray(), Encoding.UTF8);
            }
            else
            {
                //create REST
                StringBuilder sb = new StringBuilder();
                sb.Append("http://h.hatena.ne.jp/api/statuses/update.xml?");
                sb.Append("status=" + Uri.EscapeDataString(status));
                if (!String.IsNullOrEmpty(keyword))
                    sb.Append("&keyword=" + Uri.EscapeDataString(keyword));
                if(!String.IsNullOrEmpty(inReplyTo))
                    sb.Append("&in_reply_to_status_id=" + inReplyTo);
                sb.Append("&source=" + Bridge.Config.AppName);
                nc.WebConnectDownloadString(new Uri(sb.ToString()), "POST", auth.GetCredential());
            }
            }catch(Exception e)
            {
                Bridge.DebugReporter.AddReport(e);
            }
        }
    }
}
